package org.streets.eis.component.model;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.util.string.Strings;

public abstract class LoadableRowModel<T> extends LoadableDetachableModel<T>{
	private static final long serialVersionUID = 1L;
	
	private String id;

	public LoadableRowModel(T object){
		try {
			Field field = object.getClass().getField("id");			
			Object id;
			
			if ((field.getModifiers() | Modifier.PUBLIC) == Modifier.PUBLIC) {				
				id = field.get(object);
			} else {
				Method method	 = object.getClass().getMethod("get"+Strings.capitalize(field.getName()));
				id = method.invoke(object);
			}
			if (String.class.isAssignableFrom(id.getClass())){
				this.id = (String) id;
			} else {
				throw new IllegalArgumentException("Unable to find public id Field or getId method in Class " + field.getClass().getName());
			}				
		} catch (SecurityException e) {
			throw new IllegalArgumentException(e);
		} catch (NoSuchFieldException e) {
			throw new IllegalArgumentException(e);
		} catch (IllegalArgumentException e) {
			throw new IllegalArgumentException(e);
		} catch (IllegalAccessException e) {
			throw new IllegalArgumentException(e);
		} catch (NoSuchMethodException e) {
			throw new IllegalArgumentException(e);
		} catch (InvocationTargetException e) {
			throw new IllegalArgumentException(e);
		}
		
	}
	
	public LoadableRowModel(String id){
		if (id == null || id.length() == 0){
			throw new IllegalArgumentException();
		}
		this.id = id;
	}

	public String getId(){
		return this.id;
	}
	
	@Override
	public int hashCode(){
		return id.hashCode();
	}

	@Override
	public boolean equals(final Object obj)	{
		if (obj == this){
			return true;
		}else if (obj == null){
			return false;
		}else if (obj instanceof LoadableRowModel){
			LoadableRowModel<?> other = (LoadableRowModel<?>)obj;
			return this.id.equals(other.id);
		}
		return false;
	}


}
